﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using WcfContrib.Extensions.Context;
using System.ServiceModel.Description;
using WcfContrib.Helpers;
using WcfContrib.Extensions.Behaviors;
using WcfContrib.Configuration;

namespace WcfContrib.Hosting
{
    /// <summary>
    /// Represents a gneric service host
    /// </summary>
    /// <typeparam name="T">The service implementation type</typeparam>
    public class ServiceHost<T> : ServiceHost
    {
        #region Fields
        ServiceConfigurationDescription configuration;
        #endregion

        #region Properties
        private bool applyBoosting;
        /// <summary>
        /// Gets or sets a value indicating whether to apply endpoints and bindings boosting.
        /// </summary>
        /// <value><c>true</c> if to apply endpoints and bindings boosting; otherwise, <c>false</c>.</value>
        public bool ApplyBoosting
        {
            get { return applyBoosting; }
            set { applyBoosting = value; }
        }
        #endregion

        #region Instancing
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceHost&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="baseAddresses">An array of type System.Uri that contains the base addresses for the hosted service.</param>
        public ServiceHost(params Uri[] baseAddresses)
            : base(typeof(T), baseAddresses)
        {
            OnInitialize();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceHost&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="configuration">The service configuration.</param>
        public ServiceHost(ServiceConfigurationDescription configuration)
            : base(typeof(T))
        {
            this.configuration = configuration;

            LoadConfiguration();

            OnInitialize();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceHost&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="singletonInstance">The instance of the hosted service.</param>
        /// <param name="baseAddresses">An <see cref="T:System.Array"/> of type <see cref="T:System.Uri"/> that contains the base addresses for the hosted service.</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="singletonInstance"/> is null.</exception>
        public ServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        {
            OnInitialize();
        }

        void OnInitialize()
        {
            applyBoosting = WcfContribConfigurationSection.GetSection().Services.ApplyBoosting;
        }
        #endregion

        #region Configuration
        void LoadConfiguration()
        {
            configuration.GenerateEndpoints(this);
        }
        #endregion

        /// <summary>
        /// Initializes the runtime for the service host.
        /// </summary>
        /// <exception cref="T:System.InvalidOperationException">The description of the service hosted is null.</exception>
        protected override void InitializeRuntime()
        {
            AddActivationContextBehavior();

            base.InitializeRuntime();
        }

        /// <summary>
        /// Invoked during the transition of a communication object into the opening state.
        /// </summary>
        protected override void OnOpening()
        {
            if (applyBoosting)
            {
                Description.Behaviors.Add(new BoostedServiceBehaviorAttribute());
            }

            base.OnOpening();
        }

        void AddActivationContextBehavior()
        {
            Description.Behaviors.AddSafely(() => new ActivationContextInitializerBehavior());
        }
    }
}
